package com.xxh.cloud.provider.service.impl;


import com.xxh.cloud.common.config.ContentConfig;
import com.xxh.cloud.common.dto.UserDto;
import com.xxh.cloud.common.util.EncryptUtil;
import com.xxh.cloud.common.util.StringUtil;
import com.xxh.cloud.common.vo.R;
import com.xxh.cloud.provider.config.RabbitMQConfig;
import com.xxh.cloud.provider.config.RedisKeyConfig;
import com.xxh.cloud.provider.entry.User;

import com.xxh.cloud.provider.entry.UserLog;
import com.xxh.cloud.provider.mapper.UserLogMapper;
import com.xxh.cloud.provider.mapper.UserMapper;
import com.xxh.cloud.provider.service.inft.UserService;
import com.xxh.cloud.provider.until.JwtUtil;
import com.xxh.cloud.provider.until.RedissonUtil;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Map;

/**
 * @author ASUS
 * @date 2021/9/2 18:37
 */
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper mapper;
    @Autowired
    private UserLogMapper logMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Value("${cloud.auth.passkey}")
    private String key;

    //登录
    @Override
    public R loginAccount(UserDto dto) {
       //1、入参效验
        if (dto != null){
            if (!StringUtil.isEmpty(dto.getPhone(),dto.getPwd())){
               //2、查询数据
                User user = mapper.selectByPhone(dto.getPhone());
                //3、根据账号情况进行效验
                if (user == null){
                    return  R.fail("账号或密码有误");
                }else if (user.getFlag() == ContentConfig.USER_STATUS_OK){  //判断账号的状态
                    //账号有效
                    //4、效验密码
                    if (user.getPassword().equals(EncryptUtil.aesenc(key,dto.getPwd()))){
                        //5、生成令牌
                        String token = JwtUtil.createToken(EncryptUtil.aesenc(key, user.getId() + ""));
                        //6、记录操作日志
                        logMapper.insert(new UserLog(user.getId(),ContentConfig.USER_LOG_LOGIN1,"用户使用账号密码进行无状态登陆",new Date(),""));

                        return R.ok(token);
                    }else {
                        return R.fail("账号或密码错误");
                    }
                }else {
                    return R.fail("账号异常，请联系管理员");
                }

            }

        }


        return R.fail("非法的请求参数");
    }

    //注册
    @Override
    public R register(UserDto dto) {
        //1、入参效验
        if (dto != null) {
            //2、通过用户手机号查询用户信息
            User user = mapper.selectByPhone(dto.getPhone());
            //3、效验手机号是否可用
            if (user == null) {
                user = new User();
                user.setPhone(dto.getPhone());
                //4、将明文转换为密文  数据库记录的是密文  AES加密  一个加密一个解密
                user.setPassword(EncryptUtil.aesenc(key, dto.getPwd()));
                user.setFlag(ContentConfig.USER_STATUS_OK);
                //5、执行数据库操作
                if (mapper.insert(user)>0){
                    //6、记录操作日志
                    logMapper.insert(new UserLog(user.getId(),ContentConfig.USER_LOG_ADD,"新用户注册",new Date(),""));
                    return R.ok();
                }else {
                    return R.fail("注册失败，数据库操作异常");
                }

            } else {
                return R.fail("注册失败，手机号已被使用");
            }
        }else {
            return R.fail("注册失败，参数异常");
        }

    }
//手机验证码登录
    @Override
    public R loginCode(UserDto dto) {
      //1、入参效验
       if (dto != null){
            //判断手机号和验证码是否为空
           if (!StringUtil.isEmpty(dto.getPhone(),dto.getPwd())){
               String key = RedisKeyConfig.LOGIN_CODE+ dto.getPhone();
                //2、效验验证码是否存在
               if (RedissonUtil.checkKeys(key)){
                    //存在验证码
                   //3、效验验证码
                    if (dto.getPwd().equals(RedissonUtil.getStr(key))){
                        //4、查询当前在线的次数
                        String key2 = RedisKeyConfig.LOGIN_TOKEN+dto.getPhone();
                        boolean isFirst = false; //判读是否是第一次登录
                        //查询令牌是否存在
                        if (RedissonUtil.checkKeys(key2)){
                         //5、获取手机号对应的所有令牌
                            Map<Object, Object> tokens = RedissonUtil.getMap(key2);
                            int i =0;
                            //遍历所有令牌 查看是否有效
                            for (Object o:tokens.entrySet()) {
                                //6、验证令牌的有效期
                                if((System.currentTimeMillis()-Long.parseLong(tokens.get(o).toString()))/6000>ContentConfig.TOKEN_TIME){
                                    //7、令牌失效  删除
                                    RedissonUtil.delHash(key2,o);
                                }else {
                                    //计数
                                    i++;
                                }
                                //8、验证在线次数有没有达到上限
                                if (1>ContentConfig.ONLIN_NUMS){
                                    //9、踢掉所有的令牌
                                    RedissonUtil.delKeys(key2);
                                    return R.fail("当前用户登录次数超过已达上限");
                                }
                            }

                        }else {
                            isFirst = true ;//记录  证明是第一次
                        }
                        //10、登录成功，生成令牌（有效期30分钟）  有状态-Redis存储
                        String token = JwtUtil.createToken(dto.getPhone());
                        //11、存储到Redis
                        //如果是第一次登陆设置有效期 如果是第六次就踢掉所有
                        RedissonUtil.addHash(key2,token,new Date().getTime());
                        if (isFirst){
                            //12、如果第一次，需要Hash类型 设置有效期
                            RedissonUtil.expire(key2,RedisKeyConfig.LOGIN_TOKEN_TIME);

                        }
                        //13、删除验证码 保证验证码的一次性
                        RedissonUtil.delKeys(RedisKeyConfig.LOGIN_CODE+dto.getPhone());
                        //14.如果是第一次，自动注册，基于RabbitMQ 实现解耦操作 异步
                             rabbitTemplate.convertAndSend("", RabbitMQConfig.QUEUE_USER_ADD,dto.getPhone());
                        //自动注册
                        return R.ok(token);
                    }
               }else {
                   return R.fail("亲！验证码失效");
               }

           }
       }
        return R.fail("非法请求");
    }

    @Override
    public R checkToken(String token) {
        //1、入参效验
        if (!StringUtil.isEmpty(token)) {
            //2、解析令牌获取手机号
            String phone = JwtUtil.parseToken(token);
            if (!StringUtil.isEmpty(phone)){
                //4、效验手机号
                if (RedissonUtil.checkHash(RedisKeyConfig.LOGIN_TOKEN+phone,token)){
                    return R.ok();
                }
            }
        }


        return R.fail("数据无效");
    }
}
